package com.platform.common.aops;

import javax.annotation.Resource;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

@Aspect
@Component
public class ApiCallAdvice {
    
    private static final Logger LOGGER = LoggerFactory.getLogger("inte");
    
    @Resource
//    private RedisUtils redisUtils;

    private static final String FORMAT_PATTERN_DAY = "yyyy-MM-dd";

    /**
     * 配置织入点
     */
    @Pointcut("@annotation(com.pangu.common.annotation.ApiCall)")
    public void apiCall(){}

    /**
     * 真正执行业务操作前，先进行总的限流的验证
     * 限制纬度为：一天内单个IP的访问次数
     * key = URI +IP + date(精确到无)
     * value = 调用次数
     */
    @Before("apiCall()")
    public void before(){
        // 接收到请求，记录请求内容
//        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
//
//        javax.servlet.http.HttpServletRequest request = attributes.getRequest();
//        String uri = request.getRequestURI();
//        String date = dateFormat(FORMAT_PATTERN_DAY);
//        String ip = IpUtils.getIpAddr(request);
//
//        if(StringUtils.isEmpty(ip)){
//            LOGGER.error("execute uri {} error, Unauthorized access@ ip cannot");
//            throw new ApiCallException(Recode.IP_ERROR.getCode(), Recode.IP_ERROR.getDesc());
//        }
//
//        // URL+IP+日期 构成以天为纬度的key
//        String ipKey = "API_LIMIT_DAY:" + uri +"_" + ip + "_"+date;
//        if(redisUtils.hasKey(ipKey)){
//            if(Integer.parseInt(redisUtils.get(ipKey).toString()) > 10000){
//                LOGGER.error("execute uri {} error, exceed max call limit!,IP is:");
//                throw new ApiCallException(Recode.IP_ERROR.getCode(), Recode.IP_ERROR.getDesc());
//            }
//            redisUtils.incr(ipKey, 1);
//        }else{
//            redisUtils.set(ipKey, 1, 1L, TimeUnit.DAYS);
//        }
    }

    /**
     * 环绕通知：基于注解实现限流
     * @param pjp
     * @return
     */
//    @Around(value = "apiCall()")
//    public Object requestLimitAround(ProceedingJoinPoint pjp){
//        MethodSignature methodSignature = (MethodSignature)pjp.getSignature();
//        ApiCall apiCall = methodSignature.getMethod().getAnnotation(ApiCall.class);
//        // 限制访问次数
//        long limitCount = apiCall.limitCount();
//
//        HttpServletRequest request = RequestContextHolder.getRequestAttributes();
//        String requestIp = IpUtils.getIpAddr(request);
//
//        if(StringUtils.isEmpty(requestIp)){
//            LOGGER.error("execute uri {} error, exceed max call limit!,IP is:");
//            throw new ApiCallException(Recode.IP_ERROR.getCode(), Recode.IP_ERROR.getDesc());
//        }
//
//        // 获取uri
//        String uri = request.getRequestURI();
//        String key = "API_LIMIT:"+uri+"_"+requestIp+"_";
//        int size = redisUtils.keys(key+"*").size();
//        if(size>limitCount){
//            LOGGER.error("execute uri {} error, exceed max call limit!,IP is {}", methodSignature.);
//            throw new ApiCallException(Recode.IP_ERROR.getCode(), Recode.IP_ERROR.getDesc());
//        }
//
//        // 将访问存进缓存
//        redisUtils.set(key+System.currentTimeMillis(), "1", apiCall.time(), apiCall.timeUnit());
//    }

    /**
     * 递增
     * @param key
     * @param delta
     * @return
     */
//    public long incr(String key, long delta){
//        if(delta < 0){
//            throw new RuntimeException("递增因子必须大于0");
//        }
//        return redisTemplate.opsForValue().increment(key, delta);
//    }
}
